package com.hipac.hq;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.CollectionListModel;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 生成属性的get set方法，并将属性上的注释添加到方法上
 * Created by huqiang on 15/8/15.
 */
public class GenerateGSAction extends AnAction {

		private static final String GET = "获取";
		private static final String SET = "设置";

		@Override
		public void actionPerformed (AnActionEvent e) {
				generateGSMethod(getPsiMethodFromContext(e));
		}

		/**
		 * 启动写线程
		 *
		 * @param psiMethod
		 */
		private void generateGSMethod (final PsiClass psiMethod) {
				new WriteCommandAction.Simple(psiMethod.getProject(), psiMethod.getContainingFile()) {
						@Override
						protected void run () throws Throwable {
								createGetSet(psiMethod);
						}
				}.execute();
		}

		private void createGetSet (PsiClass psiClass) {
				List<PsiField> fields = new CollectionListModel<PsiField>(psiClass.getFields()).getItems();
				if (fields == null) {
						return;
				}
				List<PsiMethod> list = new CollectionListModel<PsiMethod>(psiClass.getMethods()).getItems();
				Set<String> methodSet = new HashSet<String>();
				for (PsiMethod m : list) {
						methodSet.add(m.getName());
				}
				PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(psiClass.getProject());

				for (PsiField field : fields) {
						if (field.getModifierList().hasModifierProperty(PsiModifier.FINAL)) {
								continue;
						}
						String methodText = buildGet(field);
						PsiMethod toMethod = elementFactory.createMethodFromText(methodText, psiClass);
						if (methodSet.contains(toMethod.getName())) {
								continue;
						}
						psiClass.add(toMethod);

						methodText = buildSet(field);
						elementFactory = JavaPsiFacade.getElementFactory(psiClass.getProject());
						toMethod = elementFactory.createMethodFromText(methodText, psiClass);
						if (methodSet.contains(toMethod)) {
								continue;
						}
						psiClass.add(toMethod);
				}
		}

		private String buildGet (PsiField field) {
				StringBuilder sb = new StringBuilder();
				String doc = format(GET,field);
				if(doc != null){
						sb.append(doc);
				}
				sb.append("public ");
				//判断字段是否是static
				if (field.getModifierList().hasModifierProperty(PsiModifier.STATIC)) {
						sb.append("static ");
				}
				sb.append(field.getType().getPresentableText() + " ");
				if (field.getType().getPresentableText().equals("boolean")) {
						sb.append("is");
				} else {
						sb.append("get");
				}
				sb.append(getFirstUpperCase(field.getName()));
				sb.append("(){\n");
				sb.append(" return this." + field.getName() + ";}\n");

				return sb.toString();
		}

		private String buildSet (PsiField field) {
				StringBuilder sb = new StringBuilder();
				String doc = format(SET,field);
				if(doc != null){
						sb.append(doc);
				}
				sb.append("public ");
				//判断字段是否是static
				if (field.getModifierList().hasModifierProperty(PsiModifier.STATIC)) {
						sb.append("static ");
				}
				sb.append("void ");
				sb.append("set" + getFirstUpperCase(field.getName()));
				sb.append("(" + field.getType().getPresentableText() + " " + field.getName() + "){\n");
				sb.append("this." + field.getName() + " = " + field.getName() + ";");
				sb.append("}");
				return sb.toString();
		}

		private String getFirstUpperCase (String oldStr) {
				return oldStr.substring(0, 1).toUpperCase() + oldStr.substring(1);
		}

		private PsiClass getPsiMethodFromContext (AnActionEvent e) {
				PsiElement elementAt = getPsiElement(e);
				if (elementAt == null) {
						return null;

				}
				return PsiTreeUtil.getParentOfType(elementAt, PsiClass.class);
		}

		private PsiElement getPsiElement (AnActionEvent e) {
				PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
				Editor editor = e.getData(PlatformDataKeys.EDITOR);
				if (psiFile == null || editor == null) {
						e.getPresentation().setEnabled(false);
						return null;
				}
				//用来获取当前光标处的PsiElement
				int offset = editor.getCaretModel().getOffset();
				return psiFile.findElementAt(offset);
		}

		private String format(String string,PsiField field){
				String oldContent;
				if(field.getDocComment() == null){
						oldContent = field.getText().substring(0,field.getText().lastIndexOf("\n")+1);
				}else{
						oldContent = field.getDocComment().getText();
				}
				if(oldContent.startsWith("//")){
						oldContent = oldContent.replace("// ","// "+string+" ");
				}else if(oldContent.startsWith("/**")){
						String content = oldContent.replace("/**\n","").replace("*/","").replace("\n","").trim();
						oldContent = oldContent.replace(content,content.replace("* ","* "+string+" "));
				}
				return oldContent;
		}


}
